home *** CD-ROM | disk | FTP | other *** search
/ Freelog 15 / FREELOG 15.ISO / WebMaster / Perl / PERL5106.ZIP / perl5 / Lib / Cwd.pm < prev    next >
Encoding:
Perl POD Document  |  1995-12-02  |  6.1 KB  |  263 lines

  1. package Cwd;
  2. require 5.000;
  3. require Exporter;
  4. require Config;
  5.  
  6. # Use osname for portability switches (doubled to cheaply avoid -w warning)
  7. my $osname = $Config::Config{'osname'} || $Config::Config{'osname'};
  8.  
  9.  
  10. =head1 NAME
  11.  
  12. getcwd - get pathname of current working directory
  13.  
  14. =head1 SYNOPSIS
  15.  
  16.     use Cwd;
  17.     $dir = cwd;
  18.  
  19.     use Cwd;
  20.     $dir = getcwd;
  21.  
  22.     use Cwd;
  23.     $dir = fastgetcwd;
  24.  
  25.     use Cwd 'chdir';
  26.     chdir "/tmp";
  27.     print $ENV{'PWD'};
  28.  
  29. =head1 DESCRIPTION
  30.  
  31. The getcwd() function re-implements the getcwd(3) (or getwd(3)) functions
  32. in Perl.
  33.  
  34. The fastgetcwd() function looks the same as getcwd(), but runs faster.
  35. It's also more dangerous because you might conceivably chdir() out of a
  36. directory that you can't chdir() back into.
  37.  
  38. The cwd() function looks the same as getcwd and fastgetcwd but is
  39. implemented using the most natural and safe form for the current
  40. architecture. For most systems it is identical to `pwd` (but without
  41. the trailing line terminator). It is recommended that cwd (or another
  42. *cwd() function) is used in I<all> code to ensure portability.
  43.  
  44. If you ask to override your chdir() built-in function, then your PWD
  45. environment variable will be kept up to date.  (See
  46. L<perlsub/Overriding builtin functions>.) Note that it will only be
  47. kept up to date it all packages which use chdir import it from Cwd.
  48.  
  49. =cut
  50.  
  51. @ISA = qw(Exporter);
  52. @EXPORT = qw(cwd getcwd fastcwd);
  53. @EXPORT_OK = qw(chdir);
  54.  
  55. use strict;
  56.  
  57. sub cwd {  # The 'natural and safe form' for UNIX (pwd may be setuid root)
  58.     my $cwd;
  59.     chomp($cwd = `pwd`);
  60.     $cwd;
  61.  
  62.  
  63. # By Brandon S. Allbery
  64. #
  65. # Usage: $cwd = getcwd();
  66.  
  67. sub getcwd
  68. {
  69.     my($dotdots, $cwd, @pst, @cst, $dir, @tst);
  70.  
  71.     unless (@cst = stat('.'))
  72.     {
  73.     warn "stat(.): $!";
  74.     return '';
  75.     }
  76.     $cwd = '';
  77.     $dotdots = '';
  78.     do
  79.     {
  80.     $dotdots .= '/' if $dotdots;
  81.     $dotdots .= '..';
  82.     @pst = @cst;
  83.     unless (opendir(PARENT, $dotdots))
  84.     {
  85.         warn "opendir($dotdots): $!";
  86.         return '';
  87.     }
  88.     unless (@cst = stat($dotdots))
  89.     {
  90.         warn "stat($dotdots): $!";
  91.         closedir(PARENT);
  92.         return '';
  93.     }
  94.     if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
  95.     {
  96.         $dir = '';
  97.     }
  98.     else
  99.     {
  100.         do
  101.         {
  102.         unless (defined ($dir = readdir(PARENT)))
  103.             {
  104.             warn "readdir($dotdots): $!";
  105.             closedir(PARENT);
  106.             return '';
  107.         }
  108.         unless (@tst = lstat("$dotdots/$dir"))
  109.         {
  110.             warn "lstat($dotdots/$dir): $!";
  111.             closedir(PARENT);
  112.             return '';
  113.         }
  114.         }
  115.         while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
  116.            $tst[1] != $pst[1]);
  117.     }
  118.     $cwd = "$dir/$cwd";
  119.     closedir(PARENT);
  120.     } while ($dir);
  121.     chop($cwd); # drop the trailing /
  122.     $cwd;
  123. }
  124.  
  125.  
  126.  
  127. # By John Bazik
  128. #
  129. # Usage: $cwd = &fastcwd;
  130. #
  131. # This is a faster version of getcwd.  It's also more dangerous because
  132. # you might chdir out of a directory that you can't chdir back into.
  133.  
  134. sub fastcwd {
  135.     my($odev, $oino, $cdev, $cino, $tdev, $tino);
  136.     my(@path, $path);
  137.     local(*DIR);
  138.  
  139.     ($cdev, $cino) = stat('.');
  140.     for (;;) {
  141.     my $direntry;
  142.     ($odev, $oino) = ($cdev, $cino);
  143.     chdir('..');
  144.     ($cdev, $cino) = stat('.');
  145.     last if $odev == $cdev && $oino == $cino;
  146.     opendir(DIR, '.');
  147.     for (;;) {
  148.         $direntry = readdir(DIR);
  149.         next if $direntry eq '.';
  150.         next if $direntry eq '..';
  151.  
  152.         last unless defined $direntry;
  153.         ($tdev, $tino) = lstat($direntry);
  154.         last unless $tdev != $odev || $tino != $oino;
  155.     }
  156.     closedir(DIR);
  157.     unshift(@path, $direntry);
  158.     }
  159.     chdir($path = '/' . join('/', @path));
  160.     $path;
  161. }
  162.  
  163.  
  164. # Keeps track of current working directory in PWD environment var
  165. # Usage:
  166. #    use Cwd 'chdir';
  167. #    chdir $newdir;
  168.  
  169. my $chdir_init = 0;
  170.  
  171. sub chdir_init {
  172.     if ($ENV{'PWD'}) {
  173.     my($dd,$di) = stat('.');
  174.     my($pd,$pi) = stat($ENV{'PWD'});
  175.     if (!defined $dd or !defined $pd or $di != $pi or $dd != $pd) {
  176.         $ENV{'PWD'} = cwd;
  177.     }
  178.     }
  179.     else {
  180.     $ENV{'PWD'} = cwd;
  181.     }
  182.     # Strip an automounter prefix (where /tmp_mnt/foo/bar == /foo/bar)
  183.     if ($ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|) {
  184.     my($pd,$pi) = stat($2);
  185.     my($dd,$di) = stat($1);
  186.     if (defined $pd and defined $dd and $di == $pi and $dd == $pd) {
  187.         $ENV{'PWD'}="$2$3";
  188.     }
  189.     }
  190.     $chdir_init = 1;
  191. }
  192.  
  193. sub chdir {
  194.     my $newdir = shift || '';    # allow for no arg (chdir to HOME dir)
  195.     $newdir =~ s|///*|/|g;
  196.     chdir_init() unless $chdir_init;
  197.     return 0 unless CORE::chdir $newdir;
  198.     if ($osname eq 'VMS') { return $ENV{'PWD'} = $ENV{'DEFAULT'} }
  199.  
  200.     if ($newdir =~ m#^/#) {
  201.     $ENV{'PWD'} = $newdir;
  202.     } else {
  203.     my @curdir = split(m#/#,$ENV{'PWD'});
  204.     @curdir = ('') unless @curdir;
  205.     my $component;
  206.     foreach $component (split(m#/#, $newdir)) {
  207.         next if $component eq '.';
  208.         pop(@curdir),next if $component eq '..';
  209.         push(@curdir,$component);
  210.     }
  211.     $ENV{'PWD'} = join('/',@curdir) || '/';
  212.     }
  213.     1;
  214. }
  215.  
  216.  
  217. # --- PORTING SECTION ---
  218.  
  219. # VMS: $ENV{'DEFAULT'} points to default directory at all times
  220. # 08-Dec-1994  Charles Bailey  bailey@genetics.upenn.edu
  221. # Note: Use of Cwd::getcwd() or Cwd::chdir() (but not Cwd::fastcwd())
  222. #   causes the logical name PWD to be defined in the process 
  223. #   logical name table as the default device and directory 
  224. #   seen by Perl. This may not be the same as the default device 
  225. #   and directory seen by DCL after Perl exits, since the effects
  226. #   the CRTL chdir() function persist only until Perl exits.
  227. # This does not apply to other systems (where only chdir() sets PWD).
  228.  
  229. sub _vms_cwd {
  230.     return $ENV{'DEFAULT'}
  231. }
  232. sub _vms_pwd {
  233.     return $ENV{'PWD'} = $ENV{'DEFAULT'}
  234. }
  235.  
  236. sub _NT_cwd {
  237.   main::NTGetCwd @_;
  238. }
  239.  
  240. if ($osname eq 'VMS') {
  241.  
  242.     *cwd        = \&_vms_pwd;
  243.     *getcwd     = \&_vms_pwd;
  244.     *fastgetcwd = \&_vms_cwd;
  245. }
  246. elsif ($osname eq 'MSWin32') {
  247.     *cwd        = \&_NT_cwd;
  248.     *getcwd     = \&_NT_cwd;
  249.     *fastgetcwd = \&_NT_cwd;
  250. }
  251.  
  252. # package main; eval join('',<DATA>) || die $@;    # quick test
  253.  
  254. 1;
  255.  
  256. __END__
  257. BEGIN { import Cwd qw(:DEFAULT chdir); }
  258. print join("\n", cwd, getcwd, fastcwd, "");
  259. chdir('..');
  260. print join("\n", cwd, getcwd, fastcwd, "");
  261. print "$ENV{PWD}\n";
  262.